#include "frameopenglwidget.h"

FrameOpenGLWidget::FrameOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{
    m_size.setWidth(1);
    m_size.setHeight(1);
    m_zoomSize.setWidth(1);
    m_zoomSize.setHeight(1);
    m_pos.setX(0);
    m_pos.setY(0);
    m_nInitFrameDataFormat = FrameDataFormat_NV12;
}

FrameOpenGLWidget::~FrameOpenGLWidget()
{
    if(m_yData != nullptr)
    {
        delete []m_yData;
        m_yData = nullptr;
    }

    if(m_uData != nullptr)
    {
        delete []m_uData;
        m_uData = nullptr;
    }

    if(m_vData != nullptr)
    {
        delete []m_vData;
        m_vData = nullptr;
    }

    if(m_uvData != nullptr)
    {
        delete []m_uvData;
        m_uvData = nullptr;
    }

    if(m_rgbData != nullptr)
    {
        delete []m_rgbData;
        m_rgbData = nullptr;
    }

    if(m_rgb32Data != nullptr)
    {
        delete []m_rgb32Data;
        m_rgb32Data = nullptr;
    }

    makeCurrent();

    switch (m_nInitFrameDataFormat) {
        case FrameDataFormat_RGB24:
            releaseTextureByRGBFrame();
            break;

        case FrameDataFormat_RGB32:
            releaseTextureByRGB32Frame();
            break;

        case FrameDataFormat_YUV420P:
            releaseTextureByYUV420PFrame();
            break;

        case FrameDataFormat_NV12:
            releaseTextureByNV12Frame();
            break;
    }

    doneCurrent();
}

void  FrameOpenGLWidget::setFrameDataFormat(FrameDataFormat eFrameDataFormat)
{
    if(m_nInitFrameDataFormat != eFrameDataFormat)
    {
        makeCurrent();
        m_nInitFrameDataFormat = eFrameDataFormat;

        switch (m_nInitFrameDataFormat) {
            case FrameDataFormat_RGB24:
                 releaseTextureByRGBFrame();
                // 初始化纹理
                initTextureByRGBFrame();
                initializeGLByRGBFrame();
                break;

            case FrameDataFormat_RGB32:
                releaseTextureByRGB32Frame();
                 // 初始化纹理
                initTextureByRGB32Frame();
                initializeGLByRGB32Frame();
                break;

            case FrameDataFormat_YUV420P:
                releaseTextureByYUV420PFrame();
                // 初始化纹理
                initTextureByYUV420PFrame();
                initializeGLByYUV420PFrame();
                break;

            case FrameDataFormat_NV12:
                releaseTextureByNV12Frame();
                // 初始化纹理
                initTextureByNV12Frame();
                initializeGLByNV12Frame();
                break;
        }

        doneCurrent();
    }
}
FrameDataFormat FrameOpenGLWidget::getFrameDataFormat()
{
    return (FrameDataFormat)m_nInitFrameDataFormat;
}

//更新NV12帧数据
void FrameOpenGLWidget::updateNV12Frame(const uint8_t* yData, const uint8_t* uvData, int y_linesize, int uv_linesize, int width, int height)
{
    if(m_yData == nullptr || m_uvData == nullptr)
    {
       if(m_yData != nullptr)
        {
           delete []m_yData;
        }
       if(m_uvData != nullptr)
       {
           delete []m_uvData;
       }
        m_yData = new uint8_t[y_linesize*height + 1];
        m_uvData = new uint8_t[uv_linesize*height/2 + 1];
    }
    else
    {
        if(width != m_width || height != m_height)
        {
            if(m_yData != nullptr && m_uvData != nullptr)
            {
                delete []m_yData;
                delete []m_uvData;
                m_yData = new uint8_t[y_linesize*height + 1];
                m_uvData = new uint8_t[uv_linesize*height/2 + 1];
            }
        }
    }
    memcpy(m_yData, yData, y_linesize*height);
    memcpy(m_uvData, uvData, uv_linesize*height/2);

    m_width = width;
    m_height = height;
    m_size.setWidth(width);
    m_size.setHeight(height);

    if(m_nFirstUpdateFrame)
    {
        resizeGL(size().width(), size().height());
        m_nFirstUpdateFrame = false;
    }

    update();
}
//更新YUV420P数据
void FrameOpenGLWidget::updateYUV420PFrame(const uint8_t* yData, const uint8_t* uData, const uint8_t* vData, int y_linesize, int u_linesize,  int v_linesize, int width, int height)
{
    if(m_yData == nullptr || m_uData == nullptr || m_vData == nullptr)
    {
        if(m_yData != nullptr)
         {
            delete []m_yData;
         }
        if(m_uData != nullptr)
         {
            delete []m_uData;
         }
        if(m_vData != nullptr)
         {
            delete []m_vData;
         }
        m_yData = new uint8_t[y_linesize*height + 1];
        m_uData = new uint8_t[u_linesize*height/2 + 1];
        m_vData = new uint8_t[v_linesize*height/2 + 1];
    }
    else
    {
        if(width != m_width || height != m_height)
        {
            if(m_yData != nullptr && m_uData != nullptr && m_vData != nullptr)
            {
                delete []m_yData;
                delete []m_uData;
                delete []m_vData;
                m_yData = new uint8_t[y_linesize*height + 1];
                m_uData = new uint8_t[u_linesize*height/2 + 1];
                m_vData = new uint8_t[v_linesize*height/2 + 1];
            }
        }
    }
    memcpy(m_yData, yData, y_linesize*height);
    memcpy(m_uData, uData, u_linesize*height/2);
    memcpy(m_vData, vData, v_linesize*height/2);

    m_width = width;
    m_height = height;
    m_size.setWidth(width);
    m_size.setHeight(height);

    if(m_nFirstUpdateFrame)
    {
        resizeGL(size().width(), size().height());
        m_nFirstUpdateFrame = false;
    }

    update();
}
//更新RGB24数据
void FrameOpenGLWidget::updateRGB24Frame(const uint8_t* rgbData, int width, int height, int linesize)
{
   if(m_rgbData == nullptr)
   {
       m_rgbData = new uint8_t[linesize*height + 1000];
   }
   else
   {
       if(width != m_width || height != m_height)
       {
           if(m_rgbData != nullptr)
           {
               delete []m_rgbData;
               m_rgbData = new uint8_t[linesize*height + 1000];
           }
       }
   }
   memcpy(m_rgbData, rgbData, linesize*height);

    m_width = width;
    m_height = height;
    m_size.setWidth(width);
    m_size.setHeight(height);

    if(m_nFirstUpdateFrame)
    {
        resizeGL(size().width(), size().height());
        m_nFirstUpdateFrame = false;
    }

    update();
}
//更新RGB32数据
void FrameOpenGLWidget::updateRGB32Frame(const uint8_t* rgbData, int width, int height, int linesize)
{
    if(m_rgb32Data == nullptr)
    {
        m_rgb32Data = new uint8_t[linesize*height + 1000];
    }
    else
    {
        if(width != m_width || height != m_height)
        {
            if(m_rgb32Data != nullptr)
            {
                delete []m_rgb32Data;
                m_rgb32Data = new uint8_t[linesize*height + 1000];
            }
        }
    }
    memcpy(m_rgb32Data, rgbData, linesize*height);

    m_width = width;
    m_height = height;
    m_size.setWidth(width);
    m_size.setHeight(height);

    if(m_nFirstUpdateFrame)
    {
        resizeGL(size().width(), size().height());
        m_nFirstUpdateFrame = false;
    }

    update();
}
//更新帧数据
void FrameOpenGLWidget::updateFrame(int eFrameDataFormat,  uint8_t **data, int *linesize, int width, int height)
{
    switch (eFrameDataFormat) {
        case FrameDataFormat_RGB24:
            updateRGB24Frame(data[0], width, height, linesize[0]);
            break;

        case FrameDataFormat_RGB32:
             updateRGB32Frame(data[0], width, height, linesize[0]);
            break;

        case FrameDataFormat_YUV420P:
            updateYUV420PFrame(data[0],data[1],data[2], linesize[0], linesize[1],linesize[2], width,height);
            break;

        case FrameDataFormat_NV12:
            updateNV12Frame(data[0],data[1],linesize[0], linesize[1],width,height);
            break;
    }
}

void FrameOpenGLWidget::initializeGLByNV12Frame()
{
    m_program.removeAllShaders();

    // 编译着色器
    m_program.addShaderFromSourceCode(QOpenGLShader::Vertex,
        "#version 330 core\n"
        "layout(location = 0) in vec4 vertexIn;\n"
        "layout(location = 1) in vec2 textureIn;\n"
        "out vec2 textureCoord;\n"
        "void main(void)\n"
        "{\n"
        "    gl_Position = vertexIn;\n"
        "    textureCoord = textureIn;\n"
        "}\n");

    m_program.addShaderFromSourceCode(QOpenGLShader::Fragment,
        "#version 330 core\n"
        "in vec2 textureCoord;\n"
        "out vec4 fragColor;\n"
        "uniform sampler2D tex_y;\n"
        "uniform sampler2D tex_uv;\n"
        "void main()\n"
        "{\n"
        "    float y = texture(tex_y, textureCoord).r;\n"
        "    vec2 uv = texture(tex_uv, textureCoord).rg;\n"
        "    y = 1.1643 * (y - 0.0625);\n"
        "    float u = uv.x - 0.5;\n"
        "    float v = uv.y - 0.5;\n"
        "    fragColor = vec4(\n"
        "        y + 1.5958 * v,\n"
        "        y - 0.39173 * u - 0.81290 * v,\n"
        "        y + 2.017 * u,\n"
        "        1.0\n"
        "    );\n"
        "}\n");
    m_program.link();
}
void FrameOpenGLWidget::initTextureByNV12Frame()
{
    // 初始化纹理
    glGenTextures(1, &m_yTexture);
    glGenTextures(1, &m_uvTexture);
}
void FrameOpenGLWidget::releaseTextureByNV12Frame()
{
    glDeleteTextures(1, &m_yTexture);
    glDeleteTextures(1, &m_uvTexture);
}
void FrameOpenGLWidget::paintGLByNV12Frame()
{
    if (!m_yData || !m_uvData) return;

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

#if 1
    glViewport(m_pos.x(), m_pos.y(), m_zoomSize.width(), m_zoomSize.height());  // 设置视图大小实现图片自适应
#endif

    m_program.bind();

    // 更新Y纹理
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_yTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_width, m_height, 0, GL_RED, GL_UNSIGNED_BYTE, m_yData);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // 更新UV纹理
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, m_uvTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RG, m_width/2, m_height/2, 0, GL_RG, GL_UNSIGNED_BYTE, m_uvData);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // 设置纹理单元
    m_program.setUniformValue("tex_y", 0);
    m_program.setUniformValue("tex_uv", 1);

    // 绘制矩形
    static const GLfloat vertices[] = {
        -1.0f, -1.0f,
         1.0f, -1.0f,
         -1.0f, 1.0f,
         1.0f, 1.0f,
    };
    static const GLfloat texCoords[] = {
        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,
    };

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    m_program.release();
}

void FrameOpenGLWidget::initializeGLByYUV420PFrame()
{
    m_program.removeAllShaders();
    // 编译着色器
    m_program.addShaderFromSourceCode(QOpenGLShader::Vertex,
        "#version 330 core\n"
        "layout(location = 0) in vec4 vertexIn;\n"
        "layout(location = 1) in vec2 textureIn;\n"
        "out vec2 textureCoord;\n"
        "void main() {\n"
        "    gl_Position = vertexIn;\n"
        "    textureCoord = textureIn;\n"
        "}");

    m_program.addShaderFromSourceCode(QOpenGLShader::Fragment,
        "#version 330 core\n"
        "in vec2 textureCoord;\n"
        "out vec4 fragColor;\n"
        "uniform sampler2D tex_y;\n"
        "uniform sampler2D tex_u;\n"
        "uniform sampler2D tex_v;\n"
        "const mat3 yuv2rgb = mat3(\n"
        "    1.164383, 1.164383, 1.164383,\n"        // Y系数
        "    0.0,     -0.391762, 2.017232,\n"         // U系数
        "    -0.812968, 0.0,      0.0);\n"            // V系数
        "void main() {\n"
        "    float y = texture(tex_y, textureCoord).r;\n"
        "    float u = texture(tex_u, textureCoord).r;\n"
        "    float v = texture(tex_v, textureCoord).r;\n"
        "    y = 1.1643 * (y - 0.0625);\n"
        "    u = u - 0.5;\n"
        "    v = v - 0.5;\n"
        "    fragColor = vec4(\n"
        "        y + 2.017232 * v,\n"
        "        y - 0.391762 * u - 0.812968 * v,\n"
        "        y + 1.164383 * u,\n"
        "        1.0\n"
        "    );\n"
        "}");
    m_program.link();
}
void FrameOpenGLWidget::initTextureByYUV420PFrame()
{
    // 初始化三个纹理
    glGenTextures(1, &m_yTexture);
    glGenTextures(1, &m_uTexture);
    glGenTextures(1, &m_vTexture);
}
void FrameOpenGLWidget::releaseTextureByYUV420PFrame()
{
    glDeleteTextures(1, &m_yTexture);
    glDeleteTextures(1, &m_uTexture);
    glDeleteTextures(1, &m_vTexture);
}
void FrameOpenGLWidget::paintGLByYUV420PFrame()
{
    if (!m_yData || !m_uData || !m_vData) return;

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

#if 1
    glViewport(m_pos.x(), m_pos.y(), m_zoomSize.width(), m_zoomSize.height());  // 设置视图大小实现图片自适应
#endif

    m_program.bind();

    // 更新Y纹理
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_yTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_width, m_height, 0,
                GL_RED, GL_UNSIGNED_BYTE, m_yData);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // 更新U纹理
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, m_uTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_width/2, m_height/2, 0,
                GL_RED, GL_UNSIGNED_BYTE, m_uData);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // 更新V纹理
    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, m_vTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_width/2, m_height/2, 0,
                GL_RED, GL_UNSIGNED_BYTE, m_vData);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // 设置纹理单元
    m_program.setUniformValue("tex_y", 0);
    m_program.setUniformValue("tex_u", 1);
    m_program.setUniformValue("tex_v", 2);

    // 绘制矩形
    static const GLfloat vertices[] = {
        -1.0f, -1.0f,
         1.0f, -1.0f,
        -1.0f, 1.0f,
         1.0f, 1.0f,
    };
    static const GLfloat texCoords[] = {
        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,
    };

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    m_program.release();
}

void FrameOpenGLWidget::initializeGLByRGBFrame()
{
    m_program.removeAllShaders();
    // 编译着色器
    m_program.addShaderFromSourceCode(QOpenGLShader::Vertex,
        "#version 330 core\n"
        "layout(location = 0) in vec4 vertexIn;\n"
        "layout(location = 1) in vec2 textureIn;\n"
        "out vec2 textureCoord;\n"
        "void main() {\n"
        "    vec4 adjustedPos = vertexIn;\n"
        "    gl_Position = adjustedPos;\n"
        "    textureCoord = textureIn;\n"
        "}");

    m_program.addShaderFromSourceCode(QOpenGLShader::Fragment,
        "#version 330 core\n"
        "in vec2 textureCoord;\n"
        "out vec4 fragColor;\n"
        "uniform sampler2D tex_rgb;\n"
        "void main() {\n"
        "    fragColor = texture(tex_rgb, textureCoord);\n"
        "}");
    m_program.link();

}
void FrameOpenGLWidget::initTextureByRGBFrame()
{
    // 初始化纹理
    glGenTextures(1, &m_rgbTexture);
}
void FrameOpenGLWidget::releaseTextureByRGBFrame()
{
    glDeleteTextures(1, &m_rgbTexture);
}
void FrameOpenGLWidget::paintGLByRGBFrame()
{
    if (!m_rgbData || m_width <= 0 || m_height <= 0) return;

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

#if 1
    glViewport(m_pos.x(), m_pos.y(), m_zoomSize.width(), m_zoomSize.height());  // 设置视图大小实现图片自适应
#endif

    m_program.bind();

    // 设置像素存储对齐（针对RGB24格式）
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    // 更新RGB纹理
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_rgbTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0,
                GL_RGB, GL_UNSIGNED_BYTE, m_rgbData);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    m_program.setUniformValue("tex_rgb", 0);

    // 顶点和纹理坐标
    static const GLfloat vertices[] = {
        -1.0f, -1.0f,
         1.0f, -1.0f,
        -1.0f, 1.0f,
         1.0f, 1.0f,
    };
    static const GLfloat texCoords[] = {
        0.0f, 1.0f,  // 左下
        1.0f, 1.0f,  // 右下
        0.0f, 0.0f,  // 左上
        1.0f, 0.0f   // 右上
    };

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    m_program.release();
}

void FrameOpenGLWidget::initializeGLByRGB32Frame()
{
    m_program.removeAllShaders();
    // 编译着色器
    m_program.addShaderFromSourceCode(QOpenGLShader::Vertex,
        "#version 330 core\n"
        "layout(location = 0) in vec4 vertexIn;\n"
        "layout(location = 1) in vec2 textureIn;\n"
        "out vec2 textureCoord;\n"
        "void main() {\n"
        "    vec4 pos = vertexIn;\n"
        "    gl_Position = pos;\n"
        "    textureCoord = textureIn;\n"
        "}");

    m_program.addShaderFromSourceCode(QOpenGLShader::Fragment,
        "#version 330 core\n"
        "in vec2 textureCoord;\n"
        "out vec4 fragColor;\n"
        "uniform sampler2D tex_rgb32;\n"
        "void main() {\n"
        "    fragColor = texture(tex_rgb32, textureCoord);\n"
        "}");
    m_program.link();
}
void FrameOpenGLWidget::initTextureByRGB32Frame()
{
    // 初始化纹理
    glGenTextures(1, &m_rgb32Texture);
}
void FrameOpenGLWidget::releaseTextureByRGB32Frame()
{
    glDeleteTextures(1, &m_rgb32Texture);
}
void FrameOpenGLWidget::paintGLByRGB32Frame()
{
    if (!m_rgb32Data || m_width <= 0 || m_height <= 0) return;

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

#if 1
    glViewport(m_pos.x(), m_pos.y(), m_zoomSize.width(), m_zoomSize.height());  // 设置视图大小实现图片自适应
#endif

    m_program.bind();

    // 设置纹理参数
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_rgb32Texture);

    // 更新纹理数据（根据具体格式选择）
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,   // 内部格式
                m_width, m_height, 0,
                GL_BGRA,          // 数据格式（根据实际数据调整）
                GL_UNSIGNED_BYTE, m_rgb32Data);

    // 设置纹理参数
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    m_program.setUniformValue("tex_rgb32", 0);

    // 顶点和纹理坐标
    static const GLfloat vertices[] = {
        -1.0f, -1.0f,  // 左下
         1.0f, -1.0f,  // 右下
        -1.0f, 1.0f,   // 左上
         1.0f, 1.0f    // 右上
    };
    static const GLfloat texCoords[] = {
        0.0f, 1.0f,    // 左下
        1.0f, 1.0f,    // 右下
        0.0f, 0.0f,    // 左上
        1.0f, 0.0f     // 右上
    };

    // 设置顶点属性
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    // 绘制
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    m_program.release();
}


void FrameOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();

    switch (m_nInitFrameDataFormat) {
        case FrameDataFormat_RGB24:
            initializeGLByRGBFrame();
            // 初始化纹理
            initTextureByRGBFrame();
            break;

        case FrameDataFormat_RGB32:
            initializeGLByRGB32Frame();
            // 初始化纹理
            initTextureByRGB32Frame();
            break;

        case FrameDataFormat_YUV420P:
            initializeGLByYUV420PFrame();
            // 初始化纹理
            initTextureByYUV420PFrame();
            break;

        case FrameDataFormat_NV12:
            initializeGLByNV12Frame();
            // 初始化纹理
            initTextureByNV12Frame();
            break;
    }

    // 指定颜色缓冲区的清除值(背景色)
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

void FrameOpenGLWidget::resizeGL(int w, int h)
{
#if 1
    //计算需要显示图片的窗口大小，用于实现长宽等比自适应显示
    if(m_size.width()  <= 0 || m_size.height() <= 0) return;

    if((double(w) / h) < (double(m_size.width()) / m_size.height()))
    {
        m_zoomSize.setWidth(w);
        m_zoomSize.setHeight(((double(w) / m_size.width()) * m_size.height()));
    }
    else
    {
        m_zoomSize.setHeight(h);
        m_zoomSize.setWidth((double(h) / m_size.height()) * m_size.width());
    }
    m_pos.setX(double(w - m_zoomSize.width()) / 2);
    m_pos.setY(double(h - m_zoomSize.height()) / 2);
    this->update(QRect(0, 0, w, h));
#else
   glViewport(0, 0, w, h);
#endif

}

void FrameOpenGLWidget::paintGL()
{
    switch (m_nInitFrameDataFormat) {
        case FrameDataFormat_RGB24:
            paintGLByRGBFrame();
            break;

        case FrameDataFormat_RGB32:
            paintGLByRGB32Frame();
            break;

        case FrameDataFormat_YUV420P:
            paintGLByYUV420PFrame();
            break;

        case FrameDataFormat_NV12:
            paintGLByNV12Frame();
            break;
    }
}
